; Automatically closes handle when a new (or null) program is indicated
; Otherwise, keeps the process handle open between calls that specify the
; same program. When finished reading memory, call this function with no
; parameters to close the process handle i.e: "Closed := ReadMemory()"
ReadMemory(MADDRESS=0,PROGRAM="")
{
   Static OLDPROC, ProcessHandle
   VarSetCapacity(MVALUE,4,0)
   If PROGRAM != %OLDPROC%
   {
      WinGet, pid, pid, % OLDPROC := PROGRAM
      ProcessHandle := ( ProcessHandle ? 0*(closed:=DllCall("CloseHandle"
      ,"UInt",ProcessHandle)) : 0 )+(pid ? DllCall("OpenProcess"
      ,"Int",16,"Int",0,"UInt",pid) : 0)
   }
   If (ProcessHandle) && DllCall("ReadProcessMemory","UInt"
   ,ProcessHandle,"UInt",MADDRESS,"Str",MVALUE,"UInt",4,"UInt *",0)
   return *(&MVALUE+3)<<24 | *(&MVALUE+2)<<16 | *(&MVALUE+1)<<8 | *(&MVALUE)
   return !ProcessHandle ? "Handle Closed: " closed : "Fail"
}

ReadMemoryShortInt(MADDRESS=0,PROGRAM="")
{
   Static OLDPROC, ProcessHandle
   VarSetCapacity(MVALUE,2,0)
   If PROGRAM != %OLDPROC%
   {
      WinGet, pid, pid, % OLDPROC := PROGRAM
      ProcessHandle := ( ProcessHandle ? 0*(closed:=DllCall("CloseHandle"
      ,"UInt",ProcessHandle)) : 0 )+(pid ? DllCall("OpenProcess"
      ,"Int",16,"Int",0,"UInt",pid) : 0)
   }
   If (ProcessHandle) && DllCall("ReadProcessMemory","UInt"
   ,ProcessHandle,"UInt",MADDRESS,"Str",MVALUE,"UInt",4,"UInt *",0)
   return  *(&MVALUE+1)<<8 | *(&MVALUE)
   return !ProcessHandle ? "Handle Closed: " closed : "Fail"
}

ReadMemoryByte(MADDRESS=0,PROGRAM="")
{
   Static OLDPROC, ProcessHandle
   VarSetCapacity(MVALUE,2,0)
   If PROGRAM != %OLDPROC%
   {
      WinGet, pid, pid, % OLDPROC := PROGRAM
      ProcessHandle := ( ProcessHandle ? 0*(closed:=DllCall("CloseHandle"
      ,"UInt",ProcessHandle)) : 0 )+(pid ? DllCall("OpenProcess"
      ,"Int",16,"Int",0,"UInt",pid) : 0)
   }
   If (ProcessHandle) && DllCall("ReadProcessMemory","UInt"
   ,ProcessHandle,"UInt",MADDRESS,"Str",MVALUE,"UInt",4,"UInt *",0)
   return  *(&MVALUE)
   return !ProcessHandle ? "Handle Closed: " closed : "Fail"
}

ReadMemory_Str(MADDRESS, pOffset = 0, PID = "") 
{ 
		
		winget, PID, PID, Atlantica
	
		if (PID == ""){
  
               MsgBox The specified process could not be found.
               return
			}
         
         ProcessHandle := DllCall("OpenProcess", "Int", 24, "Char", 0, "UInt", pid, "Uint")
         teststr =
		 tmp:=0
         Loop
         {
            Output := "x"  ; Put exactly one character in as a placeholder. used to break loop on null
            tempVar := DllCall("ReadProcessMemory", "UInt", ProcessHandle, "UInt", MADDRESS, "str", Output, "Uint", 1, "Uint *", 0)
            if (ErrorLevel or !tempVar)
            {
				
              DllCall("CloseHandle", "int", ProcessHandle)
              return teststr
            }
			;msgbox, %output%
            if Output =
			{
				tmp+=1
			}
			else 
			{
				tmp=0
			}
			if tmp=2
				break
				
				
         
            teststr = %teststr%%Output%
            MADDRESS++
         }
         DllCall("CloseHandle", "int", ProcessHandle)
         return, teststr  
}